package com.csaba.connector.axa;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.csaba.connector.I18NServiceException;
import com.csaba.connector.ServiceException;
import com.csaba.connector.axa.model.AXABank;
import com.csaba.connector.axa.model.AXAHistoryItem;
import com.csaba.connector.axa.model.AXASession;
import com.csaba.connector.model.Account;
import com.csaba.connector.model.Amount;
import com.csaba.connector.model.HistoryItem;
import com.csaba.connector.model.Session;
import com.csaba.connector.service.AbstractAccountHistoryService;
import com.csaba.util.LoggerHelper;

public class AXAAccountHistoryService extends AbstractAccountHistoryService implements Codes
{
	private final static Logger logger = LoggerHelper.getDefaultLogger();

	@Override
	public void execute( final Session session ) throws ServiceException
	{
		if ( !( session instanceof AXASession ) )
			throw new ServiceException("Incompatible session " + AXABank.class + " != " + session.getClass().getName());
		if ( account == null || !AXABank.getInstance().equals(account.getBank()) || from == null || to == null )
			throw new ServiceException("Service is not initialized yet correctly.");

		final AXASession axa = (AXASession) session;

		final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

		final NameValuePair[] request = new NameValuePair[] {// 
		new BasicNameValuePair("AccountNumber", account.getNumber()),//
				new BasicNameValuePair("StartDate", format.format(from)),//
				new BasicNameValuePair("StopDate", format.format(to)),//
		};

		//final String accountHistoryResult = axa.doPost(AXASession.getRequestURL(REQUEST_CURRENT_TRANSACTION), request);
		final String accountHistoryResult = axa.doPost(AXASession.getRequestURL(REQUEST_TRANSACTION_HISTORY), request);

		axa.debugFile("accountHistoryResult", accountHistoryResult);

		//historyItems = processCurrentTransactionResult(accountHistoryResult, account);
		historyItems = processTransactionHistoryResult(accountHistoryResult, account);
	}

	/*
	        "__id": 0,
	        "Status": "Teljesített",
	        "RefNo": "111",
	        "Date": "2011-05-24T00:00:00.0000000+02:00",
	        "Description": "Készpénzfelvétel (ATM/VISA)",
	        "Debit": 59000,
	        "Credit": 0,
	        "StatusInfo": "",
	        "TrxNo": 111,
	        "Time": null,
	        "GIROMessage": "aaaaa",
	        "StatusCode": "4",
	        "TargetGIROName": "bbbbb",
	        "TargetBranchID": "        ",
	        "TargetAccountNumber": "",
	        "AuthorizingClientIDs": null,
	        "TimeStamp": "00000000123456ABC",
	        "AdditionalData": "PDS=N",
	        "ValueDate": "1899-12-30T00:00:00.0000000+01:00"

	 */
	@SuppressWarnings( "unused" )
	private static HistoryItem[] processCurrentTransactionResult( final String accountHistoryResult,
			final Account account ) throws ServiceException
	{
		try
		{
			if ( accountHistoryResult.contains("Exception") )
			{
				throw AXAUtil.serverError(accountHistoryResult);
			}

			final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

			final JSONArray result = new JSONArray(accountHistoryResult);
			final int count = result.length();

			final List<HistoryItem> items = new ArrayList<HistoryItem>();
			for ( int i = 0; i < count; i++ )
			{
				final JSONObject obj = result.getJSONObject(i);
				if ( !obj.getString("StatusCode").equals("4") )
					continue;

				final HistoryItem item = new AXAHistoryItem();

				final double amount = obj.getDouble("Credit") - obj.getDouble("Debit");
				item.setAmount(new Amount(amount, account.getCurrency()));
				item.setBalance(null); //no balance info is available in current transactions

				final String date = obj.getString("Date");

				try
				{
					item.setDate(date != null && date.length() > 10 ? sdf.parse(date.substring(0, 10)) : null);
				}
				catch ( final ParseException e )
				{
					logger.log(Level.SEVERE, "Failed to parse transaction date.", e);
				}

				item.setDescription(obj.getString("Description"));
				item.setOwner(account);

				AXAUtil.setStringProperty(item, obj, "Status");
				AXAUtil.setStringProperty(item, obj, "RefNo");
				AXAUtil.setStringProperty(item, obj, "StatusInfo");
				AXAUtil.setStringProperty(item, obj, "TrxNo");
				AXAUtil.setStringProperty(item, obj, "Time");
				AXAUtil.setStringProperty(item, obj, "GIROMessage");
				AXAUtil.setStringProperty(item, obj, "StatusCode");
				AXAUtil.setStringProperty(item, obj, "TargetGIROName");
				AXAUtil.setStringProperty(item, obj, "TargetBranchID");
				AXAUtil.setStringProperty(item, obj, "TargetAccountNumber");
				AXAUtil.setStringProperty(item, obj, "AuthorizingClientIDs");
				AXAUtil.setStringProperty(item, obj, "TimeStamp");
				AXAUtil.setStringProperty(item, obj, "AdditionalData");
				AXAUtil.setStringProperty(item, obj, "ValueDate");
				AXAUtil.setIntProperty(item, obj, "__id");

				items.add(item);
			}

			return items.toArray(new HistoryItem[items.size()]);
		}
		catch ( final JSONException e )
		{
			throw new I18NServiceException(AXABank.getInstance(), "err.accountHistory", e);
		}

	}

	/*
	"__id":0,
	"Status":"Completed",
	"RefNo":"197    ",
	"Date":"2011-05-04T00:00:00.0000000+02:00",
	"Description":"Credit/Internal transfer: Gyenes G\u00E1born\u00E9, AXA Bank, 17000019-11605276",
	"Debit":0.0,
	"Credit":38968,
	"Balance":38968,
	"StatusInfo":null,
	"TrxNo":133,
	"Etc":"DDINT",
	"TargetBranchID":"17000019",
	"TargetAccountNumber":"11605276",
	"TargetGiroName":"Gyenes G\u00E1born\u00E9",
	"GIROMessage":"vissza",
	"ValueDate":null},

	*/
	private static HistoryItem[] processTransactionHistoryResult( final String accountHistoryResult,
			final Account account ) throws ServiceException
	{
		try
		{
			if ( accountHistoryResult.contains("Exception") )
			{
				throw AXAUtil.serverError(accountHistoryResult);
			}

			final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

			final JSONArray result = new JSONArray(accountHistoryResult);
			final int count = result.length();

			final List<HistoryItem> items = new ArrayList<HistoryItem>();
			for ( int i = 0; i < count; i++ )
			{
				final JSONObject obj = result.getJSONObject(i);

				final HistoryItem item = new AXAHistoryItem();

				final double amount = obj.getDouble("Credit") - obj.getDouble("Debit");
				item.setAmount(new Amount(amount, account.getCurrency()));
				item.setBalance(new Amount(obj.getDouble("Balance"), account.getCurrency()));

				final String date = obj.getString("Date");

				try
				{
					item.setDate(date != null && date.length() > 10 ? sdf.parse(date.substring(0, 10)) : null);
				}
				catch ( final ParseException e )
				{
					logger.log(Level.SEVERE, "Failed to parse transaction date.", e);
				}

				item.setDescription(obj.getString("Description"));
				item.setOwner(account);

				AXAUtil.setStringProperty(item, obj, "Status");
				AXAUtil.setStringProperty(item, obj, "RefNo");
				AXAUtil.setStringProperty(item, obj, "StatusInfo");
				AXAUtil.setIntProperty(item, obj, "TrxNo");
				AXAUtil.setStringProperty(item, obj, "Etc");
				AXAUtil.setStringProperty(item, obj, "GIROMessage");
				AXAUtil.setStringProperty(item, obj, "TargetGiroName");
				AXAUtil.setStringProperty(item, obj, "TargetBranchID");
				AXAUtil.setStringProperty(item, obj, "TargetAccountNumber");
				AXAUtil.setStringProperty(item, obj, "ValueDate");
				AXAUtil.setIntProperty(item, obj, "__id");

				items.add(item);
			}

			return items.toArray(new HistoryItem[items.size()]);
		}
		catch ( final JSONException e )
		{
			throw new I18NServiceException(AXABank.getInstance(), "err.accountHistory", e);
		}

	}

	public static void main( final String[] args ) throws Exception
	{
		final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(
				"../axa.source/transactionHistory.txt")));
		final StringBuffer file = new StringBuffer();
		String line = reader.readLine();
		while ( line != null )
		{
			file.append(line);
			line = reader.readLine();
		}
		reader.close();

		final Account account = new Account();
		account.setCurrency(Currency.getInstance("HUF"));

		System.out.println("Line: " + file);
		final HistoryItem[] items = processTransactionHistoryResult(file.toString(), account);
		for ( final HistoryItem historyItem : items )
		{
			System.out.println("Item: " + historyItem);
		}
		System.out.println("finished...");

	}
}
